﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ActionPluginAPI;

namespace iMapa.Backend.ActionPlugin
{
    public class PluginHandler
    {
        static private PluginHandler instance = new PluginHandler();

        private Dictionary<string, IActionPlugin> plugins = new Dictionary<string, IActionPlugin>();

        private PluginHandler()
        {
            LoadPlugins();
        }

        static public PluginHandler getInstance()
        {
            if (null == instance)
            {
                instance = new PluginHandler();
            }
            return instance;
        }

        /// <summary>
        /// Main method to load the plugins. It checks the folder the .exe is located in
        /// and searches for all the .dlls located. For each dll found it will call
        /// the LoadPlugin method.
        /// </summary>
        /// <returns></returns>
        public int LoadPlugins()
        {
            int iPluginsLoaded = 0;
            //get the file names of the dll files in the current directory.
            string sPath = InteractMapLoader.applicationDir+"\\Plugins\\";
            System.IO.FileInfo objExeInfo = new System.IO.FileInfo(sPath);
            foreach (System.IO.FileInfo objInfo in objExeInfo.Directory.GetFiles("*.dll"))
            {
                if (LoadPlugin(objInfo.FullName))
                {
                    iPluginsLoaded++;
                }
            }
            return iPluginsLoaded;
        }

        /// <summary>
        /// Tries to load a dll as a plugin. To qualify as a plugin it must support the interface IActionPlugin
        /// </summary>
        /// <param name="sFile">Name of the dll</param>
        /// <returns>Indicates if the specified dll could be loaded as plugin</returns>
        private bool LoadPlugin(string sFile)
        {
            System.Reflection.Assembly assPlugin = System.Reflection.Assembly.LoadFile(sFile);
            Type[] tpePluginTypes = assPlugin.GetTypes();
            bool bReturn = false;
            //Check each object in the assembly
            
            foreach (Type typePlugin in tpePluginTypes)
            {
                System.Type typeInterface = typePlugin.GetInterface("ActionPluginAPI.IActionPlugin");
                if(null!=typeInterface){
                    //Found one that supports the interface. Lets create the object, have to use the original object name
                    // again, cant instantiate on an interface. This does leave us with an object we dont know anything about.
                    // Only we to store it is in the object base class.
                    object objFactory = assPlugin.CreateInstance(typePlugin.FullName);
                    //Cast it to the interface that we do know it supports : IActionPlugin
                    ActionPluginAPI.IActionPlugin objPlugin = objFactory as ActionPluginAPI.IActionPlugin;
                    //Add it to the list.
                    plugins.Add(typePlugin.FullName, objPlugin);
                }
            }
            return bReturn;
        }

        /// <summary>
        /// Returns the hashtable containing all the plugins. I wasnt feeling like creating some nice wrapper methods
        /// and made it easy on myself ;).
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, IActionPlugin> GetPlugins()
        {
            return plugins;
        }

        public IActionPlugin GetPluginsByName(string pluginType)
        {
            if (pluginType == null)
            {
                return null;
            }
            IActionPlugin plugin;
            PluginHandler.getInstance().GetPlugins().TryGetValue(pluginType, out plugin);
            return plugin;
        }
    }
}
